#include "PDTGraphVisitor.h"
#include "PDTNode.h"
#include "PDTNumVar.h"
#include "PDTNumConst.h"
#include "PDTBoolVar.h"
#include "PDTBoolConst.h"
#include "PDTFunction.h"
#include "PDTProp.h"

/*
 DefaultVistor traverses the code structure and outputs it in text form.
 */

/*
 pre is executed before traversing the children
 */
bool PDTDefaultVisitor::pre(PDTNode * me) {
	NodeTypeEnum type = me->getType();

	switch (type) {
	case PDTNumVar_Em:
		cout << ((PDTNumVar *) me)->getName();
		break;
	case PDTNumConstInt_Em:
		cout << ((PDTNumConstInt *) me)->getValue();
		break;
	case PDTNumConstDbl_Em:
		cout << ((PDTNumConstDbl *) me)->getValue();
		break;
	case PDTBoolVar_Em:
		cout << ((PDTBoolVar *) me)->getName();
		break;
	case PDTBoolConst_Em:
		cout << ((PDTBoolConst *) me)->getValue();
		break;
	case PDTAdd_Em:
		cout << "(";
		break;
	case PDTSubt_Em:
		cout << "(";
		break;
	case PDTMult_Em:
		cout << "(";
		break;
	case PDTDiv_Em:
		cout << "(";
		break;
	case PDTMod_Em:
		cout << "(";
		break;

	case PDTAssign_Em:
		;
		break;
	case PDTWhile_Em:
		cout << "while( ";
		break;
	case PDTFunctionDec_Em:
		cout << ((PDTFunctionDec*) me)->name << " (";
		break;
	case PDTIfElse_Em:
		cout << "if( ";
		break;
	case PDTAnd_Em:
		cout << "(";
		break;
	case PDTOr_Em:
		cout << "(";
		break;
	case PDTLessThan_Em:
		cout << "(";
		break;
	case PDTGreaterThan_Em:
		cout << "(";
		break;
	case PDTLessThanEqual_Em:
		cout << "(";
		break;
	case PDTGreaterThanEqual_Em:
		cout << "(";
		break;
	case PDTEqualNum_Em:
		cout << "(";
		break;
	case PDTEqualBool_Em:
		cout << "(";
		break;
	case PDTNotEqualNum_Em:
		cout << "(";
		break;
	case PDTNotEqualBool_Em:
		cout << "(";
		break;
	case PDTNeg_Em:
		cout << "-";
		break;
	case PDTNot_Em:
		cout << "!";
		break;
	case PDTListOfStatements_Em:
		;
		break;
	default:
		;
	}
	return true;
}
/*
 in is executed between two children traversals (starts after the first child and ends after the last child)
 */
bool PDTDefaultVisitor::afterChild(PDTNode * me, PDTNode* child, unsigned int i) {
    NodeTypeEnum type = me->getType();
    //NodeTypeEnum childType=child->getType();
    switch (type) {
        /*	case (PDTNumVar_Em||PDTNumConstInt_Em||PDTNumConstDbl_Em||PDTBoolVar_Em||PDTBoolConst_Em):
            break;
         */
        case PDTAdd_Em:
            if (i == 0)
                cout << "+";
            break;
        case PDTSubt_Em:
            if (i == 0)
                cout << "-";
            break;
        case PDTMult_Em:
            if (i == 0)
                cout << "*";
            break;
        case PDTDiv_Em:
            if (i == 0)
                cout << "/";
            break;
        case PDTMod_Em:
            if (i == 0)
                cout << "%";
            break;
        case PDTAssign_Em:
            if (i == 0)
                cout << "=";
            break;
        case PDTWhile_Em:
            if (i == 0)
                cout << ") {\n";
            break;
        case PDTFunctionDec_Em:{
                                   PDTFunctionDec & func = *((PDTFunctionDec*) me);
                                   if (i < func.getChildren().size() - 3 )
                                       cout << " ";
                                   else if (i == func.getChildren().size() - 3)
                                       cout << ") {\n ";
                                   else if (i == func.getChildren().size() - 2)
                                       cout << "return ";
                               }break;
        case PDTIfElse_Em:
                               if (i == 0)
                                   cout << ") {\n";
                               else if (i == 1)
                                   cout << "}\nelse {\n";
                               break;
        case PDTAnd_Em:
                               if (i == 0)
                                   cout << "&&";
                               break;
        case PDTOr_Em:
                               if (i == 0)
                                   cout << "||";
                               break;
        case PDTLessThan_Em:
                               if (i == 0)
                                   cout << "<";
                               break;
        case PDTGreaterThan_Em:
                               if (i == 0)
                                   cout << ">";
                               break;
        case PDTLessThanEqual_Em:
                               if (i == 0)
                                   cout << "<=";
                               break;
        case PDTGreaterThanEqual_Em:
                               if (i == 0)
                                   cout << ">=";
                               break;
        case PDTEqualNum_Em:
                               if (i == 0)
                                   cout << "==";
                               break;
        case PDTEqualBool_Em:
                               if (i == 0)
                                   cout << "==";
                               break;
        case PDTNotEqualNum_Em:
                               if (i == 0)
                                   cout << "!=";
                               break;
        case PDTNotEqualBool_Em:
                               if (i == 0)
                                   cout << "!=";
                               break;
        case PDTNeg_Em:
                               break;
        case PDTNot_Em:
                               break;
        case PDTListOfStatements_Em:
                               ;
                               break;
        default:
                               ;
    }
    return true;

}

bool PDTDefaultVisitor::beforeChild(PDTNode * me, PDTNode* child, unsigned int i) {
    return true;
}
/*
 post is executed after traversing the children
 */
bool PDTDefaultVisitor::post(PDTNode * me) {
	NodeTypeEnum type = me->getType();
	switch (type) {
	/*	case (PDTNumVar_Em||PDTNumConstInt_Em||PDTNumConstDbl_Em||PDTBoolVar_Em||PDTBoolConst_Em):
	 break;
	 */

	case PDTAdd_Em:
		cout << ")";
		break;
	case PDTSubt_Em:
		cout << ")";
		break;
	case PDTMult_Em:
		cout << ")";
		break;
	case PDTDiv_Em:
		cout << ")";
		break;
	case PDTMod_Em:
		cout << ")";
		break;
	case PDTAssign_Em:
		cout << ";\n";
		break;
	case PDTWhile_Em:
		cout << "}\n";
		break;
	case PDTFunctionDec_Em:
		cout << ";\n}\n";
		break;
	case PDTIfElse_Em:
		cout << "}\n";
		break;
	case PDTAnd_Em:
		cout << ")";
		break;
	case PDTOr_Em:
		cout << ")";
		break;
	case PDTLessThan_Em:
		cout << ")";
		break;
	case PDTGreaterThan_Em:
		cout << ")";
		break;
	case PDTLessThanEqual_Em:
		cout << ")";
		break;
	case PDTGreaterThanEqual_Em:
		cout << ")";
		break;
	case PDTEqualNum_Em:
		cout << ")";
		break;
	case PDTEqualBool_Em:
		cout << ")";
		break;
	case PDTNotEqualNum_Em:
		cout << ")";
		break;
	case PDTNotEqualBool_Em:
		cout << ")";
		break;
	case PDTNeg_Em:
		break;

	case PDTNot_Em:
		;
		break;

	case PDTListOfStatements_Em:
		;
		break;
	default:
		;
	}
	return true;
}
/*
 utility function to convert an integer to a character
 */
char *inttochar(int i) {
	char *temp = new char(100); //maybe increase then delete.
	sprintf(temp, "%d", i);
	return temp;
}
/*
 utility function to convert a double to a character
 */
char *doubletochar(double i) {
	char *temp = new char(100); //maybe increase then delete.
	sprintf(temp, "%98f", i);
	return temp;
}

